#include <soar.h>

static void sig_child(int signo)
{/*{{{*/
    pid_t pid;
    int stat;

    while((pid=waitpid(-1, &stat, WNOHANG))>0)
        printf("child %d terminated\n", pid);
}/*}}}*/

static int func_child(SOCKET sock)
{/*{{{*/
    unsigned char *msg_in=NULL, *msg_out=NULL;
    int msg_in_size, msg_out_size;
    pid_t pid=getpid();
    int rtn;

    ALLOC_MULTI(msg_in, unsigned char, SOCK_MSG_SIZE, GO_OUT);
    //ALLOC_MULTI(msg_out, unsigned char, SOCK_MSG_SIZE, GO_OUT);

    printf("pid: %d\n", getpid());

    while(1)
    {
        if(sock_read(sock, msg_in, &msg_in_size, -1, WRAP))
        {
            fprintf(stderr, "child(%d): sock_read fail\n", pid);
            rtn=-1; goto GO_OUT;
        }

        //memcpy(msg_out, msg_in, msg_in_size);
        msg_out=msg_in;
        msg_out_size=msg_in_size;
        if(sock_write(sock, msg_out, &msg_out_size, -1, WRAP))
        {
            fprintf(stderr, "child(%d): sock_write fail\n", pid);
            rtn=-1; goto GO_OUT;
        }
    }

    rtn=0;

GO_OUT:
    FREE(msg_in);
    //FREE(msg_out);
    sock_close(sock);
    return(rtn);
}/*}}}*/

int main(int argc, char *argv[])
{/*{{{*/
    printf("pid: %d\n", getpid());

    /*----- 初始化 -----*/
    sig_set_handler(SIGCHLD, sig_child);

    /*----- 监听socket，展开thrd_ext_disp -----*/
    int server_port=20000;
    SOCKET listen_sock=sock_listen(server_port);
    if(listen_sock == INVALID_SOCKET)
    {
        printf("socket listen fail\n");
        goto GO_OUT;
    }
    struct sock_info sock_info;
    sock_get_info(listen_sock, &sock_info);
    printf("listen: %s %d\n",
            sock_info.self_ip, sock_info.self_port);

    while(1)
    {
        SOCKET new_sock=sock_accept(listen_sock, -1);
        if(new_sock == INVALID_SOCKET)
        {
            printf("socket accept fail\n");
            continue;
        }

        sock_get_info(new_sock, &sock_info);
        printf("self: %s %d\npeer: %s %d\n",
                sock_info.self_ip, sock_info.self_port,
                sock_info.peer_ip, sock_info.peer_port);

        pid_t pid=fork();
        if(pid == 0)
        {
            if(func_child(new_sock))
            {
                fprintf(stderr, "child %d abort\n", getpid());
            }
            return(0);
        }
        if(pid == -1)
        {
            fprintf(stderr, "fork child fail\n");
        }
        sock_close(new_sock);
    }

    return(0);

GO_OUT:
    sock_close(listen_sock);
    return(1);
}/*}}}*/
